home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * file cross.c:
- * calculate the intersections
- */
- #include <math.h>
- #include "GraphicsGems.h"
- #include "line.h"
- #include "box.h"
- /*
- * cross_calc:
- *
- * PURPOSE
- * calculate the intersections between the polygon
- * stored in poly and the linesegment stored in l
- * and put the intersections into psol.
- *
- * poly pointer to the structure containing the polygon
- * l pointer to the structure containing the linesegment
- * psol pointer to the pointer where intersections are stored
- * nsol current number of intersections stored
- * nsmax maximum storage in psol for intersections
- * if nsol exceeds nsmax additional storage is allocated
- *
- */
- cross_calc(poly, l, psol, nsol, nsmax)
- CONTOUR *poly;
- SEGMENT *l;
- CLIST **psol;
- short *nsol, nsmax;
- {
- SEGMENT *p;
- CLIST *sol;
- double s;
- long x, y, a, b, c;
- int psort(), type;
-
- sol = *psol;
- p = poly->_s;
- do {
- /*
- * calculate the a, b and c coefficients and determine the
- * type of intersection
- */
-
- a = (p->_to._y - p->_from._y)*(l->_to._x - l->_from._x) -
- (p->_to._x - p->_from._x)*(l->_to._y - l->_from._y);
- b = (p->_from._x - l->_from._x)*(l->_to._y - l->_from._y) -
- (p->_from._y - l->_from._y)*(l->_to._x - l->_from._x);
- c = (p->_from._x - l->_from._x)*(p->_to._y - p->_from._y) -
- (p->_from._y - l->_from._y)*(p->_to._x - p->_from._x);
- if(a == 0)
- type = (b == 0) ? COINCIDE : PARALLEL;
- else {
- if(a > 0) {
- if((b >= 0 && b <= a) &&
- (c >= 0 && c <= a))
- type = CROSS;
- else
- type = NO_CROSS;
- }
- else {
- if((b <= 0 && b >= a) &&
- (c <= 0 && c >= a))
- type = CROSS;
- else
- type = NO_CROSS;
- }
- }
- /*
- * process the interscetion found
- */
- switch(type) {
- case NO_CROSS: case PARALLEL:
- break;
-
- case CROSS:
- if(b == a || c == a || c == 0)
- break;
- if(b == 0 &&
- p_where(&(p->_prev->_from), &(p->_to), l) >= 0)
- break;
- s = (double)b/(double)a;
- if(l->_from._x == l->_to._x)
- x = l->_from._x;
- else
- x = p->_from._x +
- (int)((p->_to._x - p->_from._x)*s);
- if(l->_from._y == l->_to._y)
- y = l->_from._y;
- else
- y = p->_from._y +
- (int)((p->_to._y - p->_from._y)*s);
-
- if(*nsol == nsmax) {
- nsmax *= 2;
- *psol = sol = (CLIST *) realloc(sol, nsmax*sizeof(CLIST));
- }
- sol[*nsol]._p._x = x;
- sol[*nsol]._p._y = y;
- sol[*nsol]._type = STD;
- *nsol += 1;
- break;
-
- case COINCIDE:
- if(p_where(&(p->_prev->_from),
- &(p->_next->_to), l) > 0)
- break;
- if(l->_from._x != l->_to._x) {
- if((max(l->_from._x, l->_to._x) <
- min(p->_from._x, p->_to._x) ) ||
- (min(l->_from._x, l->_to._x) >
- max(p->_from._x, p->_to._x)) )
- break;
- if(min(l->_from._x, l->_to._x) <
- min(p->_from._x, p->_to._x) ) {
- if(*nsol == nsmax) {
- nsmax *= 2;
- *psol = sol = (CLIST *) realloc(sol, nsmax*sizeof(CLIST));
- }
- sol[*nsol]._p._x = p->_from._x;
- sol[*nsol]._p._y = p->_from._y;
- sol[*nsol]._type = DELAY;
- *nsol += 1;
- }
- if(max(l->_from._x, l->_to._x) >
- max(p->_from._x, p->_to._x) ) {
- if(*nsol == nsmax) {
- nsmax *= 2;
- *psol = sol = (CLIST *) realloc(sol, nsmax*sizeof(CLIST));
- }
- sol[*nsol]._p._x = p->_to._x;
- sol[*nsol]._p._y = p->_to._y;
- sol[*nsol]._type = DELAY;
- *nsol += 1;
- }
- }
- else {
-
- if((max(l->_from._y, l->_to._y) <
- min(p->_from._y, p->_to._y) ) ||
- (min(l->_from._y, l->_to._y) >
- max(p->_from._y, p->_to._y)) )
- break;
- if(min(l->_from._y, l->_to._y) <
- min(p->_from._y, p->_to._y) ) {
- if(*nsol == nsmax) {
- nsmax *= 2;
- *psol = sol = (CLIST *) realloc(sol, nsmax*sizeof(CLIST));
- }
- sol[*nsol]._p._x = p->_from._x;
- sol[*nsol]._p._y = p->_from._y;
- sol[*nsol]._type = DELAY;
- *nsol += 1;
- }
- if(max(l->_from._y, l->_to._y) >
- max(p->_from._y, p->_to._y) ) {
- if(*nsol == nsmax) {
- nsmax *= 2;
- *psol = sol = (CLIST *) realloc(sol, nsmax*sizeof(CLIST));
- }
- sol[*nsol]._p._x = p->_to._x;
- sol[*nsol]._p._y = p->_to._y;
- sol[*nsol]._type = DELAY;
- *nsol += 1;
- }
- }
- break;
- }
- p = p->_next;
- } while(p != poly->_s);
- qsort(sol, *nsol, sizeof(CLIST), psort);
- }
-
-
- /*
- * p_where
- *
- * PURPOSE
- * determine position of point p1 and p2 relative to
- * linesegment l.
- * Return value
- * < 0 p1 and p2 lie at different sides of l
- * = 0 one of both points lie on l
- * > 0 p1 and p2 lie at same side of l
- *
- * p1 pointer to coordinates of point
- * p2 pointer to coordinates of point
- * l pointer to linesegment
- *
- */
- p_where(p1, p2, l)
- POINT *p1, *p2;
- SEGMENT *l;
- {
- long dx, dy, dx1, dx2, dy1, dy2, p_1, p_2;
-
- dx = l->_to._x - l->_from._x;
- dy = l->_to._y - l->_from._y;
- dx1 = p1->_x - l->_from._x;
- dy1 = p1->_y - l->_from._y;
- dx2 = p2->_x - l->_to._x;
- dy2 = p2->_y - l->_to._y;
- p_1 = (dx*dy1 - dy*dx1);
- p_2 = (dx*dy2 - dy*dx2);
- if(p_1 == 0 || p_2 == 0)
- return(0);
- else {
- if((p_1 > 0 && p_2 < 0) || (p_1 < 0 && p_2 > 0))
- return(-1);
- else
- return(1);
- }
- }
-
-
- /*
- * p_inside
- *
- * PURPOSE
- * determine if the point stored in pt lies inside
- * the polygon stored in p
- * Return value:
- * FALSE pt lies outside p
- * TRUE pt lies inside p
- *
- * p pointer to the polygon
- * pt pointer to the point
- */
- boolean p_inside(p, pt)
- CONTOUR *p;
- POINT *pt;
- {
- SEGMENT l, *sp;
- CLIST *sol;
- short nsol = 0, nsmax = 2, reduce = 0, i;
- boolean on_contour(), odd;
-
- l._from._x = p->_minx-2;
- l._from._y = pt->_y;
- l._to._x = pt->_x;
- l._to._y = pt->_y;
- sol = (CLIST *) calloc(2, sizeof(CLIST));
- cross_calc(p, &l, &sol, &nsol, nsmax);
- for(i=0; i<nsol-1; i++)
- if(sol[i]._type == DELAY && sol[i+1]._type == DELAY)
- reduce++;
- free(sol);
- odd = (nsol - reduce) & 0x01;
- return(odd ? !on_contour(p, pt) : FALSE);
- }
-
- /*
- * function used for sorting
- */
- psort(p1, p2)
- CLIST *p1, *p2;
- {
- if(p1->_p._x != p2->_p._x)
- return(p1->_p._x - p2->_p._x);
- else
- return(p1->_p._y - p2->_p._y);
- }
-
-
- /*
- * on_contour
- *
- * PURPOSE
- * determine if the point pt lies on the
- * contour p.
- * Return value
- * TRUE point lies on contour
- * FALSE point lies not on contour
- *
- * p pointer to the polygon structure
- * pt pointer to the point
- */
- boolean on_contour(p, pt)
- CONTOUR *p;
- POINT *pt;
- {
- SEGMENT *sp;
- long dx1, dy1, dx2, dy2;
-
- sp = p->_s;
- do {
- if((pt->_x >= min(sp->_from._x, sp->_to._x)) &&
- (pt->_x <= max(sp->_from._x, sp->_to._x)) ) {
- dx1 = pt->_x - sp->_from._x;
- dx2 = sp->_to._x - pt->_x;
- dy1 = pt->_y - sp->_from._y;
- dy2 = sp->_to._y - pt->_y;
- if(dy1*dx2 == dy2*dx1)
- return(TRUE);
- }
- sp = sp->_next;
- } while(sp != p->_s);
- return(FALSE);
- }
-
-